今天要來做的是滾動動畫,利用滑鼠滾輪來控制BOX從左右兩邊交叉的出現,倒回去也一樣可以XD! 那我們就直接開始吧
知識點 | 使用說明 |
---|---|
flexbox |
佈局排版 |
box-shadow |
製作BOX的陰影效果 |
translateX( ) |
製作BOX的水平方向位移 |
transition |
控制BOX出現的動畫速度和效果 |
:nth-of-type() |
用來選擇"偶數號"的BOX |
知識點 | 使用說明 |
---|---|
window.innerHeight |
取得視窗內的網頁內容高度 |
Element.getBoundingClientRect() |
取得BOX距離視窗的位子 |
forEach() |
迭代每個BOX,並判斷BOX是否要顯示在畫面 |
<h1>Scroll to see the animation</h1>
<div class="box"><h2>放入你想寫的標題</h2></div>
<div class="box"><h2>放入你想寫的標題</h2></div>
<div class="box"><h2>放入你想寫的標題</h2></div>
<div class="box"><h2>放入你想寫的標題</h2></div>
<!-- 後面都一樣,所以省略 -->
* {
box-sizing: border-box;
}
body {
background-color: #efedd6;
margin: 0;
padding: 0;
display: flex; /*讓內容水平垂直置中*/
flex-direction: column;
justify-content: center;
align-items: center;
overflow-x: hidden;
}
在Day 3 progress steps進度條,我們有寫了一個CSS公版,這個公版在往後的賽project中可以作為一個初始模板,不過在這要稍微客製一下,加入flex-direction: column;
讓排版轉為直向,不用設height
,因為我們要透過滑鼠滾輪去製造效果,如果設定高度就沒意義了
主要內容
h1 {
margin: 10px;
}
.box {
background-color: rgb(158, 158, 242);
color: white;
display: flex;
justify-content: center;
align-items: center;
width: 250px;
height: 150px;
margin: 10px;
border-radius: 10px;
/* offset-x | offset-y | blur-radius | color */
box-shadow: 2px 4px 5px rgba(0, 0, 0, 0.3);
transform: translateX(400%); /*向右移動400%,若不寫預設為0*/
transition: transform 0.4s ease;
}
.box:nth-of-type(even) { /*even:偶數*/
transform: translateX(-400%);
}
.box.show {
transform: translateX(0);
}
↑ 這一段有幾個重點,第一個是使用了::nth-of-type(even)
去找出偶數號的盒子
在最一開始的完成圖中,我們看到盒子是"左右交叉"的出現,但其實只要控制一邊的出現,就可以了做到這個效果了
第二個需要注意的就是,transform: translateX(位移距離)
裡的位移距離,在預設情況下,BOX是在 transform: translateX(400%);
的位子,因為我們設置overflow-x: hidden;
,所以超過瀏覽器的範圍會被隱藏起來,不過要留意如果位移的單位是設%,它所參考的對象並非父元素,而是參考設置transform的那個元素
再來,我們為偶數號的BOX設了 transform: translateX(-400%);
,所以所有偶數號的BOX們都會向左移動-400%,不過也因為設置了overflow-x: hidden;
,所以也看不到它出現在畫面中
至於.box.show
,眼尖的你可能會注意到我們在html中並沒有寫入這個class,疑?? 不過依照前幾篇的操作不是這樣阿! 這裡就是在為後面javaScript埋伏筆呀嘿嘿,因為我們要透過show這個類別去控制BOX的出現,它在預設情況下並沒有要"show",所以就不必寫在html中了
let boxes = document.querySelectorAll(".box");
window.addEventListener("scroll", checkBoxes);
checkBoxes();
function checkBoxes() {
console.log(window.innerHeight);
let triggerBottom = window.innerHeight * 0.8;
boxes.forEach((box) => {
let boxTop = box.getBoundingClientRect().top;
if (boxTop < triggerBottom) {
box.classList.add("show");
} else {
box.classList.remove("show");
}
});
}
JS可以拆成兩部分來講解,這時候真希望你有雙螢幕,看程式碼就不用一直滾動那麼辛苦XD
首先,要設置一個checkbox函式,我們要用它來檢查每個BOX的位子,那既然我們需要檢查每個BOX的位子,就必須想辦法知道每個BOX的觸發點(trigger point)在哪,以及當滑鼠滾輪向下,BOX進入畫面時,我們要做甚麼?(好繞口令XD)
那我針對有使用到的方法做簡單的介紹:
擷取MDN上的一段話
The Window interface represents a window containing a DOM document . Read-only innerHeight property of the Window interface returns the interior height of the window in pixels, including the height of the horizontal scroll bar, if present.
意思大致上是說,window是一個包含了DOM document的物件,其中innerHeight這個屬性,它是唯讀(Read-only)的,我們可以透過它取得視窗內的網頁內容高度,如果有水平卷軸也會包含進去。
console.log(window.innerHeight);
從印出來的結果你會發現,當滾動滾輪時它會印出一個正整數,它是固定的數字(如下圖),不過我們為了要做出滑鼠滾輪的效果,它不能是固定的數字,因為在任何時候高度都有可能不同
let triggerBottom = window.innerHeight * 0.8;
triggerBottom代表觸發器的底部,值為 window.innerHeight 的 80%,你可以試試看不要乘任何數 or 乘更大 or 乘更小去測試看看,比較彼此的差別
一樣擷取MDN上的一段話
The Element.getBoundingClientRect() method returns a DOMRect object providing information about the size of an element and its position relative to the viewport.
意思大致上是說 getBoundingClientRect()
可以用來知道一個元素的大小和位子,會回傳DOMRect,DOMRect其實就是一個矩形,它提供了這個矩形的大小和位子等相關資訊,可以看底下這張圖比較好理解,left, top, right, bottom, x, y...這些都是它提供的資訊,是可以取用的屬性
本圖擷取自MDN
box.getBoundingClientRect().top;
是我們想知道BOX距離視窗的高度在哪,它有沒有小於triggerBottom
這個變數,如果小於的話,我們要新增(add()
) "show"這個類別,否則就移除(remove()
)
那今天的解說都到這邊,關於計算視窗的高度會比較難理解,自己也是透過實作的過程一邊去消化吸收,不懂的就console.log()印出來看看到底那是甚麼東西,如果有任何問題可以底下留言,我會盡我所能回答你XD
附上codepen連結 https://codepen.io/hangineer/pen/qBYNyYY?editors=1100
所學不精,若有解說不夠詳盡或是錯誤歡迎指教,感激不盡!那明天見囉
[補充]
50 Projects In 50 Days - HTML, CSS & JavaScript
網頁座標 - 了解 screen、page、client 差異